using System;
using System.Collections;

namespace DotNetCRM.Core.ExtensionMethods
{
    /// <summary>
    /// Allows you to modify the collection
    /// while within a for each loop.
    /// </summary>
    public class IteratorIsolate : IEnumerable
    {
        /// <summary>
        /// IteratorIsolateEnumerator
        /// </summary>
        internal class IteratorIsolateEnumerator : IEnumerator
        {
            protected ArrayList items = new ArrayList();
            protected int currentItem;

            /// <summary>
            /// Initializes a new instance of the <see cref="IteratorIsolateEnumerator"/> class.
            /// </summary>
            /// <param name="enumerator">The enumerator.</param>
            internal IteratorIsolateEnumerator( IEnumerator enumerator )
            {
                while(enumerator.MoveNext())
                {
                    items.Add( enumerator.Current );
                }
                IDisposable disposable = enumerator as IDisposable;
                if(disposable != null)
                {
                    disposable.Dispose();
                }
                currentItem = -1;
            }

            /// <summary>
            /// Sets the enumerator to its initial position, which is before the first element in the collection.
            /// </summary>
            /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception>
            public void Reset()
            {
                currentItem = -1;
            }

            /// <summary>
            /// Advances the enumerator to the next element of the collection.
            /// </summary>
            /// <returns>
            /// true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
            /// </returns>
            /// <exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception>
            public bool MoveNext()
            {
                currentItem++;
                if(currentItem == items.Count)
                    return false;

                return true;
            }

            /// <summary>
            /// Gets the current element in the collection.
            /// </summary>
            /// <value></value>
            /// <returns>The current element in the collection.</returns>
            /// <exception cref="T:System.InvalidOperationException">The enumerator is positioned before the first element of the collection or after the last element. </exception>
            public object Current
            {
                get
                {
                    return items[currentItem];
                }
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="IteratorIsolate"/> class.
        /// </summary>
        /// <param name="enumerable">The enumerable.</param>
        public IteratorIsolate( IEnumerable enumerable )
        {
            this.enumerable = enumerable;
        }

        /// <summary>
        /// Returns an enumerator that iterates through a collection.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerator"></see> object that can be used to iterate through the collection.
        /// </returns>
        public IEnumerator GetEnumerator()
        {
            return new IteratorIsolateEnumerator( enumerable.GetEnumerator() );
        }

        /// <summary>
        /// 
        /// </summary>
        protected IEnumerable enumerable;
    }
}